/*
 *  Openmysee
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
				 
#include "echo.h"
struct Timertask *GTimerhead;

int timer_free ()
{
	struct Timertask *pt, *prev;
	for (pt=GTimerhead; pt; pt=prev)
	{
		prev = pt->next;
		free (pt);
	}
	return 0;
}

int timer_add (unsigned int t, TimerFunc process, void *entity, void *data)
{
	struct Timertask *pt = calloc (1, sizeof (*pt)), *p, *prevp;
	if (pt == NULL)
	{
		fprintf (stderr, "Allocation failed in %s:%d\n", __FILE__, __LINE__);
		return -1;
	}
	pt->time = t;
	pt->process = process;
	pt->entity = entity;
	pt->data = data;
	pt->process = process;
	if (GTimerhead == NULL || GTimerhead->time >= t)
	{
		pt->next = GTimerhead;
		GTimerhead = pt;
	} else
	{
		for (prevp=NULL,p=GTimerhead; p&&p->time < t; prevp=p,p=p->next);
		pt->next = p;
		prevp->next = pt;
	}
	return 0;
}


int timer_process (unsigned int t)
{
	struct Timertask *p;
	for (p=GTimerhead; p; p=GTimerhead)
	{
		if (t >= p->time)
		{
			GTimerhead = p->next;
			(*(p->process)) (p->entity, p->data);
			free (p);
		} else
			break;
	}
	return 0;
}

int timer_remove (void *entity, void *data)
{
	struct Timertask *p, *nextp, *prevp;
	for (prevp=NULL, p=GTimerhead; p; p=nextp)
	{
		nextp = p->next;
		if (p->entity == entity && p->data == data)
		{
			if (GTimerhead == p)
				GTimerhead = nextp;
			else
				prevp->next = p->next;
			free (p);
		} else
			prevp = p;
	}
	return 0;
}

#ifdef __TEST_TIMER
main ()
{
	timer_add (0, NULL, 1, 1);
	timer_add (10, NULL, 1, 0);
	timer_add (5, NULL, 2, 1);
	if (GTimerhead->time != 0 || GTimerhead->next->time != 5 || GTimerhead->next->next->time != 10)
		assert (0);
	timer_remove (2, 1);
	if (GTimerhead->time != 0 || GTimerhead->next->time != 10)
		assert (0);
	timer_remove (1, 1);
	if (GTimerhead->time != 10)
		assert (0);
	timer_remove (1, 0);
	if (GTimerhead != NULL)
		assert (0);
}
#endif
